<?php
/*
 * 字串处理类
 * @package    pre
 * @author     Mark
 * @copyright  Copyright (c) 2013 ixdcw team
 * @version    $Id: d4699add822a96d7c35f62f0e2a3755ca4c49883 $
 */
class Str {

	public function __construct() {
		exit('Static Class "' . __CLASS__ . '" Can\'t Be Instanced');
	}

	/**
	 * 取消转义
	 * @param $input
	 * @return array|string
	 */
	public static function stripSlashes($input) {
		return is_array($input) ? array_map(array(__CLASS__, __FUNCTION__), $input) : stripslashes($input);
	}

	/**
	 * 转义操作
	 * @param $input
	 * @return array|string
	 */
	public static function addSlashes($input) {
		return is_array($input) ? array_map(array(__CLASS__, __FUNCTION__), $input) : addslashes($input);
	}


	/**
	 * 转义特殊字符
	 * @param      $input
	 * @param bool $preserveAmpersand
	 * @return array|mixed|string
	 */
	public static function htmlSpecialChars($input, $preserveAmpersand = true) {
		if (is_string($input)) {
			if ($preserveAmpersand) {
				return str_replace('&amp;', '&', htmlspecialchars($input, ENT_QUOTES));
			} else {
				return htmlspecialchars($input, ENT_QUOTES);
			}
		}
		if (is_array($input)) {
			foreach ($input as $key => $val) {
				$input[$key] = self::htmlSpecialChars($val, $preserveAmpersand);
			}
			return $input;
		}
		return $input;
	}

	/**
	 * 能做到代码不危害大众, 但是还不能把代码安全展示出来
	 * @param $input
	 * @return array|mixed
	 */
	public static function safe($input) {
		if (is_array($input)) {
			return array_map(array(__CLASS__, __FUNCTION__), $input);
		} else {
			if (strlen($input) < 20) return $input;
			$match   = array(
				"/&#([a-z0-9]+)([;]*)/i",
				"/(j[\s\r\n\t]*a[\s\r\n\t]*v[\s\r\n\t]*a[\s\r\n\t]*s[\s\r\n\t]*c[\s\r\n\t]*r[\s\r\n\t]*i[\s\r\n\t]*p[\s\r\n\t]*t|jscript|js|vbscript|vbs|about|expression|script|frame|link|import)/i",
				"/on(mouse|exit|error|click|dblclick|key|load|unload|change|move|submit|reset|cut|copy|select|start|stop)/i"
			);
			$replace = array(
				"",
				"<d>\\1</d>",
				"on\n\\1"
			);
			return preg_replace($match, $replace, $input);
		}
	}

	/**
	 * 删除代码中的换行符
	 * @param      $string
	 * @param bool $js
	 * @return mixed
	 */
	public static function trimEOL($string, $js = false) {
		$string = str_replace(array(chr(10), chr(13)), array('', ''), $string);
		return $js ? str_replace("'", "\'", $string) : $string;
	}

	/**
	 * 去除空格, 换行
	 * @param $string
	 * @return mixed
	 */
	public static function trimSpace($string) {
		$string = str_replace(array(chr(13), chr(10), "\n", "\r", "\t", '  '), array('', '', '', '', '', ''), $string);
		return $string;
	}

	/**
	 * @param        $string           带截取的字符串
	 * @param        $length           长度
	 * @param string $suffix           后缀
	 * @param int    $start            开始字符
	 * @return mixed|string 中文截断字符方法
	 */
	public static function cut($string, $length, $suffix = '', $start = 0) {
		if ($start) {
			$tmp    = self::cut($string, $start);
			$string = substr($string, strlen($tmp));
		}
		$strlen = strlen($string);
		if ($strlen <= $length) return $string;
		$string = str_replace(array('&quot;', '&lt;', '&gt;'), array('"', '<', '>'), $string);
		$length = $length - strlen($suffix);
		$str    = '';
		if (strtolower(DT_CHARSET) == 'utf-8') {
			$n = $tn = $noc = 0;
			while ($n < $strlen) {
				$t = ord($string{$n});
				if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
					$tn = 1;
					$n++;
					$noc++;
				} elseif (194 <= $t && $t <= 223) {
					$tn = 2;
					$n += 2;
					$noc += 2;
				} elseif (224 <= $t && $t <= 239) {
					$tn = 3;
					$n += 3;
					$noc += 2;
				} elseif (240 <= $t && $t <= 247) {
					$tn = 4;
					$n += 4;
					$noc += 2;
				} elseif (248 <= $t && $t <= 251) {
					$tn = 5;
					$n += 5;
					$noc += 2;
				} elseif ($t == 252 || $t == 253) {
					$tn = 6;
					$n += 6;
					$noc += 2;
				} else {
					$n++;
				}
				if ($noc >= $length) break;
			}
			if ($noc > $length) $n -= $tn;
			$str = substr($string, 0, $n);
		} else {
			for ($i = 0; $i < $length; $i++) {
				$str .= ord($string{$i}) > 127 ? $string{$i} . $string{++$i} : $string{$i};
			}
		}
		$str = str_replace(array('"', '<', '>'), array('&quot;', '&lt;', '&gt;'), $str);
		return $str == $string ? $str : $str . $suffix;
	}

	/**
	 * 文字 -> 16进制表示
	 * @param $str
	 * @return string
	 */
	public static function toHex($str) {
		return bin2hex($str);
	}

	/**
	 * 16进制转换为字串
	 * @param $hex
	 * @return string
	 */
	public static function fromHex($hex) {
		// php5.4
		if (function_exists('hex2bin')) return hex2bin($hex);
		$str = '';
		for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
			$str .= chr(hexdec($hex[$i] . $hex[$i + 1]));
		}
		return $str;
	}

	/**
	 * 返回随机字串, 区分大小写
	 * @param        $length
	 * @param string $chars
	 * @return string
	 */
	public static function random($length, $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz') {
		$hash = '';
		$max  = strlen($chars) - 1;
		for ($i = 0; $i < $length; $i++) {
			$hash .= $chars[mt_rand(0, $max)];
		}
		return $hash;
	}

	public static function convert($str, $fromCharset = 'utf-8', $toCharset = 'gbk') {
		if (!$str) return '';
		$fromCharset = strtolower($fromCharset);
		$toCharset   = strtolower($toCharset);
		if ($fromCharset == $toCharset) return $str;
		$fromCharset = str_replace('gbk', 'gb2312', $fromCharset);
		$toCharset   = str_replace('gbk', 'gb2312', $toCharset);
		$fromCharset = str_replace('utf8', 'utf-8', $fromCharset);
		$toCharset   = str_replace('utf8', 'utf-8', $toCharset);
		if ($toCharset == $fromCharset) return $str;
		$tmp = array();
		if (function_exists('iconv')) {
			if (is_array($str)) {
				foreach ($str as $key => $val) {
					$tmp[$key] = iconv($fromCharset, $toCharset . "//IGNORE", $val);
				}
				return $tmp;
			} else {
				return iconv($fromCharset, $toCharset . "//IGNORE", $str);
			}
		} else if (function_exists('mb_convert_encoding')) {
			if (is_array($str)) {
				foreach ($str as $key => $val) {
					$tmp[$key] = mb_convert_encoding($val, $toCharset, $fromCharset);
				}
				return $tmp;
			} else {
				return mb_convert_encoding($str, $toCharset, $fromCharset);
			}
		} else {
			return self::_convert($str, $toCharset, $fromCharset);
		}
	}

	/**
	 *
	 * @param $char
	 * @return string
	 */
	public static function ch2Utf8($char){
		$str = '';
		if ($char < 0x80) {
			$str .= $char;
		} else if ($char < 0x800) {
			$str .= (0xC0 | $char>>6);
			$str .= (0x80 | $char & 0x3F);
		} else if ($char < 0x10000) {
			$str .= (0xE0 | $char>>12);
			$str .= (0x80 | $char>>6 & 0x3F);
			$str .= (0x80 | $char & 0x3F);
		} else if ($char < 0x200000) {
			$str .= (0xF0 | $char>>18);
			$str .= (0x80 | $char>>12 & 0x3F);
			$str .= (0x80 | $char>>6 & 0x3F);
			$str .= (0x80 | $char & 0x3F);
		}
		return $str;
	}

	/**
	 * 文本->拼音
	 * Str::text2py('大众',1)   =>  d
	 * @param      $chars
	 * @param int  $length      返回的拼音的长度, 以截取为准
	 * @param bool $firstLetter 是否返回首字母, 如 '天安门' => 'tam'
	 * @return string
	 */
	public static function text2py($chars, $length = 0, $firstLetter = false) {
		$pinyin  = self::chars2py($chars, $firstLetter);
		if (!$length) {
			return implode('', $pinyin);
		} else {
			return substr(implode('', $pinyin), 0, $length);
		}
	}

	/**
	 * 文本->拼音数组
	 * @param      $chars
	 * @param bool $firstLetter
	 * @return array
	 */
	public static function chars2py($chars, $firstLetter = false) {
		$chars  = self::chars2array($chars);
		$pinyin = array();
		foreach ($chars as $char) {
			$py = self::_quickChar2py($char);
			if (!$py) {
				$py = self::_slowChar2py($char);
			}
			$pinyin[] = $firstLetter ? substr($py, 0, 1) : $py;
		}
		return $pinyin;
	}

	/**
	 * 将文字分解为数组, 支持UTF8+英文, 不支持GBK
	 * @param $str
	 * @return array
	 */
	public static function chars2array($str) {
		$array = array();
		while (strlen($str) > 0) {
			$strTest = decbin(ord(substr($str, 0, 1)));
			$strTest = str_pad($strTest, 8, '0', STR_PAD_LEFT);
			if (preg_match('/0[10]{7}/s', $strTest, $matches)) {
				$byteNum = 1;
			} elseif (preg_match('/110[10]{5}/s', $strTest, $matches)) {
				$byteNum = 2;
			} elseif (preg_match('/1110[10]{4}/s', $strTest, $matches)) {
				$byteNum = 3;
			} elseif (preg_match('/11110[10]{3}/s', $strTest, $matches)) {
				$byteNum = 4;
			}
			array_push($array, substr($str, 0, $byteNum));
			$str = substr($str, $byteNum);
		}
		return $array;
	}

	/**
	 * 检查给定的字串是否匹配指定的url规则, 完全匹配模式
	 * @param $pregRule
	 * @param $str
	 * @return bool
	 */
	public static function test($pregRule, $str) {
		if (preg_match($pregRule, $str, $match)) {
			return $match[0] === $str;
		} else {
			return false;
		}
	}

	/**
	 * 计算字符长度
	 * @param $chars
	 * @return int
	 */
	public static function length($chars){
		return count(self::chars2array($chars));
	}

	/**
	 * 计算字符长度
	 * @param $string
	 * @return int
	 */
	public static function count($string) {
		$string = self::convert($string, DT_CHARSET, 'gbk');
		$length = strlen($string);
		$count  = 0;
		for ($i = 0; $i < $length; $i++) {
			$t = ord($string[$i]);
			if ($t > 127) $i++;
			$count++;
		}
		return $count;
	}

	/**
	 * 检测字符是否为UTF8编码
	 * @param $str
	 * @return int
	 */
	public static function isUtf8($str){
		return preg_match('%^(?:
	          [\x09\x0A\x0D\x20-\x7E]            # ASCII
	        | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
	        |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
	        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
	        |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
	        |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
	        | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
	        |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
	    )*$%xs', $str);
	}

	/**
	 * gbk编码字符转换到拼音, 快速匹配模式
	 * @param $text
	 * @return string
	 */
	private static function _quickChar2py($text) {
		if (!$text) return '';
		if (strtolower(DT_CHARSET) != 'gbk') $text = self::convert($text, DT_CHARSET, 'gbk');
		$data = array();
		$tmp  = @file(DT_INC . '/attachment/gb-pinyin.table');
		if (!$tmp) return '';
		$tmps = count($tmp);
		for ($i = 0; $i < $tmps; $i++) {
			$tmp1     = explode("\t", $tmp[$i]);
			$data[$i] = array($tmp1[0], $tmp1[1]);
		}
		$r       = array();
		$k       = 0;
		$textlen = strlen($text);
		for ($i = 0; $i < $textlen; $i++) {
			$p = ord(substr($text, $i, 1));
			if ($p > 160) {
				$q = ord(substr($text, ++$i, 1));
				$p = $p * 256 + $q - 65536;
			}
			if ($p > 0 && $p < 160) {
				$r[$k] = chr($p);
			} elseif ($p < -20319 || $p > -10247) {
				$r[$k] = '';
			} else {
				for ($j = $tmps - 1; $j >= 0; $j--) {
					if ($data[$j][1] <= $p) break;
				}
				$r[$k] = $data[$j][0];
			}
			$k++;
		}
		return implode('', $r);
	}

	/**
	 * 支持单字符拼音->文字
	 * @param $char
	 * @return bool
	 */
	private static function _slowChar2py($char) {
		$file = DT_ROOT . '/attachment/pinyin.txt';
		$str  = file_get_contents($file);
		if (preg_match("/{$char}([a-z ]{1,15})/is", $str, $match)) {
			return $match[1];
		} else {
			return false;
		}
	}

	/**
	 * 字串转换函数
	 * @param        $str
	 * @param string $fromCharset
	 * @param string $toCharset
	 * @return string
	 */
	private static function _convert($str, $fromCharset = 'utf-8', $toCharset = 'gb2312') {
		$fromCharset = str_replace('utf-8', 'utf8', $fromCharset);
		$toCharset   = str_replace('utf-8', 'utf8', $toCharset);
		$tmp         = file(DT_CORE . '/attachment/gb-unicode.table');
		if (!$tmp) return $str;
		$table = array();
		while (list($key, $value) = each($tmp)) {
			if ($fromCharset == 'utf8') {
				$table[hexdec(substr($value, 7, 6))] = substr($value, 0, 6);
			} else {
				$table[hexdec(substr($value, 0, 6))] = substr($value, 7, 6);
			}
		}
		unset($tmp);
		$cStr = '';
		if ($fromCharset == 'utf8') {
			$len = strlen($str);
			$i   = 0;
			while ($i < $len) {
				$c = ord(substr($str, $i++, 1));
				switch ($c >> 4) {
					case 0:
					case 1:
					case 2:
					case 3:
					case 4:
					case 5:
					case 6:
					case 7:
						$cStr .= substr($str, $i - 1, 1);
						break;
					case 12:
					case 13:
						$char2 = ord(substr($str, $i++, 1));
						$char3 = $table[(($c & 0x1F) << 6) | ($char2 & 0x3F)];
						$cStr .= self::fromHex(dechex($char3 + 0x8080));
						break;
					case 14:
						$char2 = ord(substr($str, $i++, 1));
						$char3 = ord(substr($str, $i++, 1));
						$char4 = $table[(($c & 0x0F) << 12) | (($char2 & 0x3F) << 6) | (($char3 & 0x3F) << 0)];
						$cStr .= self::fromHex(dechex($char4 + 0x8080));
						break;
				}
			}
		} else {
			while ($str) {
				if (ord(substr($str, 0, 1)) > 127) {
					$utf8  = self::ch2Utf8(hexdec($table[hexdec(bin2hex(substr($str, 0, 2))) - 0x8080]));
					$dutf8 = strlen($utf8);
					for ($i = 0; $i < $dutf8; $i += 3) {
						$cStr .= chr(substr($utf8, $i, 3));
					}
					$str = substr($str, 2, strlen($str));
				} else {
					$cStr .= substr($str, 0, 1);
					$str = substr($str, 1, strlen($str));
				}
			}
		}
		unset($table);
		return $cStr;
	}

	/**
	 * 菊花文生成
	 * @param $str
	 * @return string
	 */
	public static function chrysanthemum($str){
		if (function_exists('mb_substr')) {
			mb_internal_encoding("UTF-8");
			$len = mb_strlen($str);
			$mb = array();
			for ($i = 0; $i < $len; $i++) {
				$mb[] = mb_substr($str, $i, 1);
			}
			$mb[] = "";
			return implode("&#1161;", $mb);
		} else {
			return $str;
		}
	}

	/**
	 * JS 转义函数
	 * @param $str
	 * @return string
	 */
	public static function jsEscape($str) {
		return addcslashes($str, "\\\'\"&\n\r<>");
	}

	/**
	 * 导出数据为Excel格式
	 * @param array  $lists //转换的数据
	 * @param array  $set  //Excel设置
	 * @param array  $firstline //第一行的数据
	 * @param string  $filename //文件名
	 */
	public static function  exportExcel($lists,$set,$firstline,$filename='default.xls'){
		$objPHPExcel = new PHPExcel();
		foreach($set as $k=>$v){
			if(empty($v) || !isset($v)){$set[$k] = 'default';}
		}
		$objWriter= new PHPExcel_Writer_Excel2007($objPHPExcel);//2007格式

		//设置excel的属性：
		$objPHPExcel->getProperties()->setCreator($set['author']);//创建人
		$objPHPExcel->getProperties()->setLastModifiedBy($set['author']);//最后修改人
		$objPHPExcel->getProperties()->setTitle($set['title']);//标题
		$objPHPExcel->getProperties()->setSubject($set['title']);//题目
		$objPHPExcel->getProperties()->setDescription($set['intru']);//描述
		$objPHPExcel->getProperties()->setKeywords($set['keyword']);//关键字
		$objPHPExcel->getProperties()->setCategory($set['category']);//种类
		$objPHPExcel->getActiveSheet()->setTitle($set['stitle']);//设置当前的sheet title
		//设置第一行的值：
		foreach($firstline as $k=>$v){
			$v = explode('|',$v);
			$v[2] = $v[2] ? $v[2] : 20;
			$objPHPExcel->getActiveSheet()->setCellValue($k.'1', $v[1]);
			$objPHPExcel->getActiveSheet()->getStyle($k.'1')->getFont()->setSize(14);//size
			$objPHPExcel->getActiveSheet()->getStyle($k.'1')->getFont()->setBold(true);//加粗
			$objPHPExcel->getActiveSheet()->getColumnDimension($k)->setWidth($v[2]);//宽度
		}
		//设置单元格的值
		foreach($lists as $s=>$t){
			$s = $s+2;
			foreach($firstline as $k=>$v){
				$v = explode('|',$v);
				$objPHPExcel->getActiveSheet()->setCellValue($k.$s, $t[$v['0']]);
			}
		}
		header("Content-Type: application/force-download");
		header("Content-Type: application/octet-stream");
		header("Content-Type: application/download");
		header('Content-Disposition:inline;filename="'.$filename.'"');
		header("Content-Transfer-Encoding: binary");
		header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
		header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Pragma: no-cache");
		$objWriter->save('php://output');
		exit();
	}

	/**
	 * 清除html字串
	 * @param $text
	 * @return string
	 */
	public static function stripTags( $text )
	{
		$text = preg_replace(
			array(
				// Remove invisible content
				'@<head[^>]*?>.*?</head>@siu',
				'@<style[^>]*?>.*?</style>@siu',
				'@<script[^>]*?.*?</script>@siu',
				'@<object[^>]*?.*?</object>@siu',
				'@<embed[^>]*?.*?</embed>@siu',
				'@<applet[^>]*?.*?</applet>@siu',
				'@<noframes[^>]*?.*?</noframes>@siu',
				'@<noscript[^>]*?.*?</noscript>@siu',
				'@<noembed[^>]*?.*?</noembed>@siu',
				// Add line breaks before and after blocks
				'@</?((address)|(blockquote)|(center)|(del))@iu',
				'@</?((div)|(h[1-9])|(ins)|(isindex)|(p)|(pre))@iu',
				'@</?((dir)|(dl)|(dt)|(dd)|(li)|(menu)|(ol)|(ul))@iu',
				'@</?((table)|(th)|(td)|(caption))@iu',
				'@</?((form)|(button)|(fieldset)|(legend)|(input))@iu',
				'@</?((label)|(select)|(optgroup)|(option)|(textarea))@iu',
				'@</?((frameset)|(frame)|(iframe))@iu',
			),
			array(
				' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
				"\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0",
				"\n\$0", "\n\$0",
			),
			$text );
		return strip_tags( $text );
	}
}